#include "PDTCodeGraph.h"
#include "PDTNode.h"
#include "PDTBehavior.h"
#include "PDTCondition.h"
#include "PDTFunction.h"

PDTCodeGraph::PDTCodeGraph()
: currentId(0), maxWhileDepth(0)
{

}

void PDTCodeGraph::addNode(PDTNode * node){
	nodes.push_back(node);
}

void PDTCodeGraph::addVar(PDTVar * var){
	variables.push_back(var);
}

void PDTCodeGraph::addConst(PDTConst * cons){
	constants.push_back(cons);
}

void PDTCodeGraph::addProp(PDTProp * prop){
	properties.push_back(prop);
}

void PDTCodeGraph::updateCurrentId(){
    currentId++;
}

void PDTCodeGraph::traverse(PDTNode * node){
	//node->traverse();
}

PDTNode* PDTCodeGraph::findPreCG(string preName, unsigned int i)
{
    PDTNode * first = NULL;
	for (; i < this->nodes.size(); i++)
	{
		PDTNode * node = this->nodes[i];
		if (node->isPreCondition())
		{
            if (first == NULL) {
                first = node;
            }
			if ((dynamic_cast<PDTPreCondition*>(node))->getName() == preName)
				return node;
		}
	}
	cerr << "PreCondition with name: "<<preName<<" is not found"<<endl;
	return first;
}

PDTNode* PDTCodeGraph::findPostCG(string postName, unsigned int i)
{
	for (; i < this->nodes.size(); i++)
	{
		PDTNode * node = this->nodes[i];
		if (node->isPostCondition())
		{
			if ((dynamic_cast<PDTPostCondition*>(node))->getName() == postName)
				return node;
		}
	}
	cout<<"PostCondition with name: "<<postName<<" is not found"<<endl;
	return NULL;
}


PDTNode* PDTCodeGraph::findBehaviorCG(string bahaviorsName, unsigned int i)
{
	for (; i < this->nodes.size(); i++)
	{
		PDTNode * node = this->nodes[i];
		if (node->isBehaviors())
		{
			if ((dynamic_cast<PDTBehaviors*>(node))->getName() == bahaviorsName)
				return node;
		}
	}
	cout<<"Behaviors with name: "<<bahaviorsName<<" is not found"<<endl;
	return NULL;
}

PDTFunctionDec * 
PDTCodeGraph::
findFunction(const string & funcName)
{
    if (funcName.empty()) {
        for (unsigned int i = 0; i < nodes.size(); i++)
        {
            PDTNode * node = nodes[i];
            if (!node->isFunctionDec()) 
                continue;
            PDTFunctionDec * func = dynamic_cast<PDTFunctionDec*>(node);
            return func;
        }
    } else {
        for (unsigned int i = 0; i < nodes.size(); i++)
        {
            PDTNode * node = nodes[i];
            if (!node->isFunctionDec()) 
                continue;
            PDTFunctionDec * func = dynamic_cast<PDTFunctionDec*>(node);
            if (func->getName() == funcName) {
                return func;
            }
        }
    }
	return NULL;
}

PDTNode * PDTCodeGraph::findFunctionCall(string funcName)
{
	for (unsigned int i = 0; i < this->nodes.size(); i++)
	{
		PDTNode * node = this->nodes[i];
		if (node->isFunctionCall())
		{
			if ((dynamic_cast<PDTFunctionCall*>(node))->getName() == funcName)
				return node;
		}
	}
	return NULL;
}

PDTNode * PDTCodeGraph::findVariable(string varName)
{
	for (unsigned int i = 0; i < this->nodes.size(); i++)
	{
		PDTNode * node = this->nodes[i];
		if (node->isNumVar())
		{
			//cout<<"Comparing: "<<(dynamic_cast<PDTNumVar*>(node))->getName()<<" and "<<varName<<endl;
			if ((dynamic_cast<PDTNumVar*>(node))->getName() == varName)
				return node;
		}
		else if (node->isBoolVar())
		{
			if ((dynamic_cast<PDTBoolVar*>(node))->getName() == varName)
				return node;
		}
		if (node->isSequenceVar())
		{
			if ((dynamic_cast<PDTSequenceVar*>(node))->getName() == varName)
				return node;
		}
	}
	return NULL;
}

void PDTCodeGraph::printAllVariables()
{
	for (unsigned int i = 0; i < this->nodes.size(); i++)
		//cout<<i<<" "<<endl;
		if (this->nodes[i]->isNumVar())
			cout<<(dynamic_cast<PDTNumVar*>(this->nodes[i]))->getName()<<endl;
}



